package com.lagou.filter;

import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author zyt
 * @createDate 2020/06/27 6:40 AM
 */
@Component
@Activate(group = {CommonConstants.CONSUMER})
public class TPMonitorFilter implements Filter {
   public static final ConcurrentHashMap<String, List<Long>> CONCURRENT_HASH_MAP = new ConcurrentHashMap<>();

    // TP90：指在一个时间段内（如1分钟），统计该方法每次调用所消耗的时间，并将这些时间按从小到大的顺序进行排序，取第90%的那个值作为TP90值
    // TP99：指在一个时间段内（如1分钟），统计该方法每次调用所消耗的时间，并将这些时间按从小到大的顺序进行排序，取第99%的那个值作为TP99值

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        long startTime = System.currentTimeMillis();
        try {
            // 执行方法
            return invoker.invoke(invocation);
        } finally {
            long endTime = System.currentTimeMillis();
            // 耗时时间
            long timeout = endTime - startTime;

            String key = invoker.getUrl().getServiceKey() + ":" + invocation.getMethodName();

            synchronized (CONCURRENT_HASH_MAP) {
                if (!CONCURRENT_HASH_MAP.containsKey(key)) {
                    ArrayList<Long> value = new ArrayList<>();
                    value.add(timeout);
                    CONCURRENT_HASH_MAP.put(key, value);
                } else {
                    List<Long> value = CONCURRENT_HASH_MAP.get(key);
                    if (value.size() > 2000) {
                        value.remove(0);
                    }
                    value.add(timeout);
                    Collections.sort(value);
                    CONCURRENT_HASH_MAP.put(key,value);
                }
            }
        }
    }

    @Scheduled(fixedRate = 5000)
    public void task(){
        int size = CONCURRENT_HASH_MAP.size();
        if (size==0){
            return;
        }
        System.out.println("=============================");
        Set<Map.Entry<String, List<Long>>> entries = CONCURRENT_HASH_MAP.entrySet();
        Iterator<Map.Entry<String, List<Long>>> iterator = entries.iterator();
        while (iterator.hasNext()){
            Map.Entry<String, List<Long>> next = iterator.next();
            String key = next.getKey();
            List<Long> value = next.getValue();

            size = value.size();

            Integer index = Double.valueOf(size * 0.9).intValue();
            System.out.println(key+" P90耗时情况: "+ value.get(index));
            index = Double.valueOf(size * 0.99).intValue();
            System.out.println(key+" P99耗时情况: "+ value.get(index));
        }
    }
}
